/*
 * Copyright (c) 2022, IMMORTA Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * - Neither the name of IMMORTA Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*!
 * @file cmp_drv.c
 * @brief This file defines cmp driver functions
 */

/*******Includes***************************************************************/
#include "cmp_reg_access.h"

/*******Definitions************************************************************/

/*******Variables**************************************************************/
/*!@brief Table to save register base addresses for cmp instances */
static CMP_Type* const s_cmpRegBase[CONFIG_CMP_INSTANCE_COUNT] = CONFIG_CMP_REG_BASE_PTRS;

/*!@brief Table to save cmp irq numbers */
static const IRQn_Type s_cmpIRQ[CONFIG_CMP_INSTANCE_COUNT] = CONFIG_CMP_IRQS;

/*! @brief CMP callback pointer */
static cmp_callback_t s_cmpCallback[CONFIG_CMP_INSTANCE_COUNT] = {NULL};

/*! @brief Table to save ipwm interrupt status */
static cmp_int_status_t s_cmpIntStatus[CONFIG_CMP_INSTANCE_COUNT] = {0U};

/*!@brief Table to save cmp module names */
static const module_names_t s_cmpModName[CONFIG_CMP_INSTANCE_COUNT] = CONFIG_CMP_MODULE_NAMES;

/*!@brief Table to save cmp clock names */
static const clk_names_t s_cmpClkName[CONFIG_CMP_INSTANCE_COUNT] = CONFIG_CMP_CLOCK_NAMES;

/*******Prototypes*************************************************************/

/*******Private Functions******************************************************/
/*******************************************************************************
 *** Function Name : CMP_ComparatorConfig
 *** Description   : Comparator parameters configuration
 ******************************************************************************/
static void CMP_ComparatorConfig(uint32_t instance, const cmp_comparator_config_t* compConfig)
{
    CMP_Type* regBase = s_cmpRegBase[instance];

    /* Set the CMP channele pre-set state */
    CMP_REG_SetChPresetState(regBase, compConfig->preSetState);

    CMP_REG_SetLoopModeSelect(regBase, compConfig->loopModeConfig.loopModeSelect);
    if ((compConfig->loopModeConfig.loopModeSelect == CMP_NO_LOOP) || (compConfig->loopModeConfig.loopModeSelect == CMP_NO_LOOP_1)) {
        /* Set comparator pos and neg port input channel */
        CMP_REG_SetPosPortInput(regBase, compConfig->posInput);
        CMP_REG_SetNegPortInput(regBase, compConfig->negInput);
    } else {
        /* Set loop mode config */
        if (compConfig->loopModeConfig.loopModeSelect == CMP_NEG_LOOP) {
            CMP_REG_SetPosPortInput(regBase, compConfig->posInput);
        } else if (compConfig->loopModeConfig.loopModeSelect == CMP_POS_LOOP) {
            CMP_REG_SetNegPortInput(regBase, compConfig->negInput);
        }

        CMP_REG_SetLoopFreqDivide(regBase, compConfig->loopModeConfig.loopFreDiv);
        CMP_REG_SetLoopSequence(regBase, compConfig->loopModeConfig.loopSequence);
        CMP_REG_SetParallelOutputEnable(regBase, compConfig->loopModeConfig.parallelOutputEn);
        if (true == compConfig->loopModeConfig.parallelOutputEn) {
            CMP_REG_SetParallelOutputASelect(regBase, compConfig->loopModeConfig.posA);
            CMP_REG_SetParallelOutputBSelect(regBase, compConfig->loopModeConfig.posB);
            CMP_REG_SetParallelOutputCSelect(regBase, compConfig->loopModeConfig.posC);
            CMP_REG_SetParallelOutputDSelect(regBase, compConfig->loopModeConfig.posD);
        }
    }

    /* Set invert status */
    CMP_REG_SetInverterStatus(regBase, compConfig->invertEn);
    /* Set window enable or disable */
    CMP_REG_SetWindowEnable(regBase, compConfig->windowEn);
    /* Set digital filter */
    CMP_REG_SetDigFilterEnable(regBase, compConfig->digFilterConfig.filterEn);
    CMP_REG_SetDigFilterClkDiv(regBase, compConfig->digFilterConfig.filterClockDiv);
    CMP_REG_SetDigFilterWidth(regBase, compConfig->digFilterConfig.filterWidth);
    /* Set comparator hystersis voltage */
    CMP_REG_SetHysteresisVoltage(regBase, compConfig->hysteresisVolt);

    /* Set comparator output select signal */
    CMP_REG_SetComparatorOutputSelect(regBase, compConfig->outputSelect);
    /* Set comparator output to pin status */
    CMP_REG_SetOutputPinStatus(regBase, compConfig->cmpOutPinEn);
    /* Set channel switch and cmp enable initial delay */
    CMP_REG_SetInitDelay(regBase, compConfig->initDelay);

    s_cmpCallback[instance] = compConfig->callBack;
    /* Clear all flags */
    CMP_REG_ClrIntFlags(regBase);
    /* Set edge interrupt type */
    CMP_REG_SetEdgeInt(regBase, compConfig->edgeType);
    /* Set interrupt enable or disable */
    CMP_REG_SetIntEnable(regBase, compConfig->intEn);
    if (true == compConfig->intEn) {
        NVIC_EnableIRQ(s_cmpIRQ[instance]);
    } else {
        NVIC_DisableIRQ(s_cmpIRQ[instance]);
    }

    /* Set cmp enable or disable */
    CMP_REG_SetComparatorEnable(regBase, compConfig->cmpEn);
}

/*******************************************************************************
 *** Function Name : CMP_DacConfig
 *** Description   : Dac parameters configuration
 ******************************************************************************/
static void CMP_DacConfig(uint32_t instance, const cmp_dac_config_t* dacConfig)
{
    CMP_Type* regBase = s_cmpRegBase[instance];

    /* Set dac output */
    CMP_REG_SetDacPinEnable(regBase, dacConfig->dacPinEn);
    CMP_REG_SetDacVoltRef(regBase, dacConfig->dacRefVolt);
    CMP_REG_SetDacVoltValue(regBase, dacConfig->dacValue);
    CMP_REG_SetDacEnable(regBase, dacConfig->dacEn);
}

/*******Code*******************************************************************/

/*******************************************************************************
 *** Function Name : CMP_Init
 *** Description   : Comparator and dac parameters initialize
 ******************************************************************************/
void CMP_Init(uint32_t instance, const cmp_config_t* cmpConfig)
{
    ASSERT_PARAM(cmpConfig != NULL);
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    /* Select cmp function clock source */
    (void)CLOCK_SelectModuleClockSource(s_cmpClkName[instance], (uint16_t)(cmpConfig->comp.srcClk));
    /* Enable cmp module clock */
    CLOCK_SetModuleBusClockEnable(s_cmpModName[instance], true);
    /* Set soft reset inactive of cmp module */
    CLOCK_SetModuleSoftResetState(s_cmpModName[instance], RESET_INACTIVE);

    CMP_DacConfig(instance, &(cmpConfig->dac));
    CMP_ComparatorConfig(instance, &(cmpConfig->comp));
}

/*******************************************************************************
 *** Function Name : CMP_GetInitConfig
 *** Description   : Get comparator and dac initialize configuration
 ******************************************************************************/
void CMP_GetInitConfig(uint32_t instance, cmp_config_t* cmpConfig)
{
    ASSERT_PARAM(cmpConfig != NULL);
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    CMP_Type* regBase = s_cmpRegBase[instance];

    /* Get comparator configuration */
    cmpConfig->comp.preSetState = CMP_REG_GetChPresetState(regBase);
    cmpConfig->comp.posInput = CMP_REG_GetPosPortInput(regBase);
    cmpConfig->comp.negInput = CMP_REG_GetNegPortInput(regBase);
    cmpConfig->comp.loopModeConfig.loopModeSelect = CMP_REG_GetLoopModeSelect(regBase);
    cmpConfig->comp.loopModeConfig.loopFreDiv = CMP_REG_GetLoopFreqDivide(regBase);
    cmpConfig->comp.loopModeConfig.loopSequence = CMP_REG_GetLoopSequence(regBase);
    cmpConfig->comp.loopModeConfig.parallelOutputEn = CMP_REG_GetParallelOutputEnable(regBase);
    cmpConfig->comp.loopModeConfig.posA = CMP_REG_GetParallelOutputASelect(regBase);
    cmpConfig->comp.loopModeConfig.posB = CMP_REG_GetParallelOutputBSelect(regBase);
    cmpConfig->comp.loopModeConfig.posC = CMP_REG_GetParallelOutputCSelect(regBase);
    cmpConfig->comp.loopModeConfig.posD = CMP_REG_GetParallelOutputDSelect(regBase);

    cmpConfig->comp.invertEn = CMP_REG_GetInverterStatus(regBase);
    cmpConfig->comp.windowEn = CMP_REG_GetWindowEnable(regBase);
    cmpConfig->comp.digFilterConfig.filterEn = CMP_REG_GetDigFilterEnable(regBase);
    cmpConfig->comp.digFilterConfig.filterClockDiv = CMP_REG_GetDigFilterClkDiv(regBase);
    cmpConfig->comp.digFilterConfig.filterWidth = CMP_REG_GetDigFilterWidth(regBase);
    cmpConfig->comp.hysteresisVolt = CMP_REG_GetHysteresisVoltage(regBase);

    cmpConfig->comp.outputSelect = CMP_REG_GetComparatorOutputSelect(regBase);
    cmpConfig->comp.cmpOutPinEn = CMP_REG_GetOutputPinStatus(regBase);
    cmpConfig->comp.edgeType = CMP_REG_GetEdgeInt(regBase);
    cmpConfig->comp.intEn = CMP_REG_GetIntEnable(regBase);
    cmpConfig->comp.initDelay = CMP_REG_GetInitDelay(regBase);
    /* Get dac configuration */
    cmpConfig->dac.dacPinEn = CMP_REG_GetDacPinEnable(regBase);
    cmpConfig->dac.dacRefVolt = CMP_REG_GetDacVoltRef(regBase);
    cmpConfig->dac.dacValue = CMP_REG_GetDacVoltValue(regBase);
    cmpConfig->dac.dacEn = CMP_REG_GetDacEnable(regBase);

    cmpConfig->comp.cmpEn = CMP_REG_GetComparatorEnable(regBase);
}

/*******************************************************************************
 *** Function Name : CMP_Deinit
 *** Description   : Comparator and dac parameters default value initialize
 ******************************************************************************/
void CMP_Deinit(uint32_t instance)
{
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    s_cmpCallback[instance] = NULL;
    /* Set soft reset active of cmp module */
    CLOCK_SetModuleSoftResetState(s_cmpModName[instance], RESET_ACTIVE);
    /* Disable cmp module clock */
    CLOCK_SetModuleBusClockEnable(s_cmpModName[instance], false);

    NVIC_DisableIRQ(s_cmpIRQ[instance]);
    NVIC_ClearPendingIRQ(s_cmpIRQ[instance]);
}

/*******************************************************************************
 *** Function Name : CMP_GetDefaultConfig
 *** Description   : Get comparator and dac default configuration with reset value
 ******************************************************************************/
void CMP_GetDefaultConfig(cmp_config_t* cmpConfig)
{
    ASSERT_PARAM(cmpConfig != NULL);

    /* Get comparator default configuration */
    cmpConfig->comp.srcClk = CMP_CLK_SRC_OFF;
    cmpConfig->comp.preSetState = 0U;
    cmpConfig->comp.posInput = BG_VOLTAGE;
    cmpConfig->comp.negInput = BG_VOLTAGE;
    cmpConfig->comp.loopModeConfig.loopModeSelect = CMP_NO_LOOP;
    cmpConfig->comp.loopModeConfig.loopFreDiv = 0U;
    cmpConfig->comp.loopModeConfig.loopSequence = 0U;
    cmpConfig->comp.loopModeConfig.parallelOutputEn = false;
    cmpConfig->comp.loopModeConfig.posA = CMP_EXTERNAL_CH0;
    cmpConfig->comp.loopModeConfig.posB = CMP_EXTERNAL_CH0;
    cmpConfig->comp.loopModeConfig.posC = CMP_EXTERNAL_CH0;
    cmpConfig->comp.loopModeConfig.posD = CMP_EXTERNAL_CH0;

    cmpConfig->comp.invertEn = false;
    cmpConfig->comp.windowEn = false;
    cmpConfig->comp.digFilterConfig.filterEn = false;
    cmpConfig->comp.digFilterConfig.filterClockDiv = 0U;
    cmpConfig->comp.digFilterConfig.filterWidth = 0U;
    cmpConfig->comp.hysteresisVolt = CMP_HYS_0MV;

    cmpConfig->comp.outputSelect = CMP_OUT_AFTER_FILTER;
    cmpConfig->comp.cmpOutPinEn = false;
    cmpConfig->comp.edgeType = CMP_FALL_EDGE_INT;
    cmpConfig->comp.intEn = false;
    cmpConfig->comp.initDelay = 0U;
    /* Get dac default configuration */
    cmpConfig->dac.dacPinEn = false;
    cmpConfig->dac.dacRefVolt = CMP_DAC_BANDGAP;
    cmpConfig->dac.dacValue = 0U;
    cmpConfig->dac.dacEn = false;

    cmpConfig->comp.cmpEn = false;
}

/*******************************************************************************
 *** Function Name : CMP_ComparatorInit
 *** Description   : Comparator parameters initialize
 ******************************************************************************/
void CMP_ComparatorInit(uint32_t instance, const cmp_comparator_config_t* compConfig)
{
    ASSERT_PARAM(compConfig != NULL);
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    /* Select cmp function clock source */
    (void)CLOCK_SelectModuleClockSource(s_cmpClkName[instance], (uint16_t)(compConfig->srcClk));
    /* Enable cmp module clock */
    CLOCK_SetModuleBusClockEnable(s_cmpModName[instance], true);
    /* Set soft reset inactive of cmp module */
    CLOCK_SetModuleSoftResetState(s_cmpModName[instance], RESET_INACTIVE);

    CMP_ComparatorConfig(instance, compConfig);
}

/*******************************************************************************
 *** Function Name : CMP_GetComparatorInitConfig
 *** Description   : Get comparator initialize configuration
 ******************************************************************************/
void CMP_GetComparatorInitConfig(uint32_t instance, cmp_comparator_config_t* compConfig)
{
    ASSERT_PARAM(compConfig != NULL);
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    CMP_Type* regBase = s_cmpRegBase[instance];

    /* Get comparator initial configuration */
    compConfig->preSetState = CMP_REG_GetChPresetState(regBase);
    compConfig->posInput = CMP_REG_GetPosPortInput(regBase);
    compConfig->negInput = CMP_REG_GetNegPortInput(regBase);
    compConfig->loopModeConfig.loopModeSelect = CMP_REG_GetLoopModeSelect(regBase);
    compConfig->loopModeConfig.loopFreDiv = CMP_REG_GetLoopFreqDivide(regBase);
    compConfig->loopModeConfig.loopSequence = CMP_REG_GetLoopSequence(regBase);
    compConfig->loopModeConfig.parallelOutputEn = CMP_REG_GetParallelOutputEnable(regBase);
    compConfig->loopModeConfig.posA = CMP_REG_GetParallelOutputASelect(regBase);
    compConfig->loopModeConfig.posB = CMP_REG_GetParallelOutputBSelect(regBase);
    compConfig->loopModeConfig.posC = CMP_REG_GetParallelOutputCSelect(regBase);
    compConfig->loopModeConfig.posD = CMP_REG_GetParallelOutputDSelect(regBase);

    compConfig->invertEn = CMP_REG_GetInverterStatus(regBase);
    compConfig->windowEn = CMP_REG_GetWindowEnable(regBase);
    compConfig->digFilterConfig.filterEn = CMP_REG_GetDigFilterEnable(regBase);
    compConfig->digFilterConfig.filterClockDiv = CMP_REG_GetDigFilterClkDiv(regBase);
    compConfig->digFilterConfig.filterWidth = CMP_REG_GetDigFilterWidth(regBase);
    compConfig->hysteresisVolt = CMP_REG_GetHysteresisVoltage(regBase);
    compConfig->outputSelect = CMP_REG_GetComparatorOutputSelect(regBase);
    compConfig->cmpOutPinEn = CMP_REG_GetOutputPinStatus(regBase);
    compConfig->initDelay = CMP_REG_GetInitDelay(regBase);
    compConfig->edgeType = CMP_REG_GetEdgeInt(regBase);
    compConfig->intEn = CMP_REG_GetIntEnable(regBase);
    compConfig->cmpEn = CMP_REG_GetComparatorEnable(regBase);
}

/*******************************************************************************
 *** Function Name : CMP_GetComparatorDefaultConfig
 *** Description   : Get comparator default configuration with reset value
 ******************************************************************************/
void CMP_GetComparatorDefaultConfig(cmp_comparator_config_t* compConfig)
{
    ASSERT_PARAM(compConfig != NULL);

    /* Get comparator default configuration */
    compConfig->srcClk = CMP_CLK_SRC_OFF;
    compConfig->preSetState = 0U;
    compConfig->posInput = BG_VOLTAGE;
    compConfig->negInput = BG_VOLTAGE;
    compConfig->loopModeConfig.loopModeSelect = CMP_NO_LOOP;
    compConfig->loopModeConfig.loopFreDiv = 0U;
    compConfig->loopModeConfig.loopSequence = 0U;
    compConfig->loopModeConfig.parallelOutputEn = false;
    compConfig->loopModeConfig.posA = CMP_EXTERNAL_CH0;
    compConfig->loopModeConfig.posB = CMP_EXTERNAL_CH0;
    compConfig->loopModeConfig.posC = CMP_EXTERNAL_CH0;
    compConfig->loopModeConfig.posD = CMP_EXTERNAL_CH0;

    compConfig->invertEn = false;
    compConfig->windowEn = false;
    compConfig->digFilterConfig.filterEn = false;
    compConfig->digFilterConfig.filterClockDiv = 0U;
    compConfig->digFilterConfig.filterWidth = 0U;
    compConfig->hysteresisVolt = CMP_HYS_0MV;

    compConfig->outputSelect = CMP_OUT_AFTER_FILTER;
    compConfig->cmpOutPinEn = false;
    compConfig->initDelay = 0U;

    compConfig->edgeType = CMP_FALL_EDGE_INT;
    compConfig->intEn = false;
    compConfig->cmpEn = false;
}

/*******************************************************************************
 *** Function Name : CMP_DacInit
 *** Description   : Dac parameters initialize
 ******************************************************************************/
void CMP_DacInit(uint32_t instance, const cmp_dac_config_t* dacConfig)
{
    ASSERT_PARAM(dacConfig != NULL);
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    /* Select cmp function clock source */
    (void)CLOCK_SelectModuleClockSource(s_cmpClkName[instance], (uint16_t)(dacConfig->srcClk));
    /* Enable cmp module clock */
    CLOCK_SetModuleBusClockEnable(s_cmpModName[instance], true);
    /* Set soft reset inactive of cmp module */
    CLOCK_SetModuleSoftResetState(s_cmpModName[instance], RESET_INACTIVE);

    CMP_DacConfig(instance, dacConfig);
}

/*******************************************************************************
 *** Function Name : CMP_GetDacInitConfig
 *** Description   : Get dac initialize configuration
 ******************************************************************************/
void CMP_GetDacInitConfig(uint32_t instance, cmp_dac_config_t* dacConfig)
{
    ASSERT_PARAM(dacConfig != NULL);
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    CMP_Type* regBase = s_cmpRegBase[instance];

    /* Get dac initial configuration */
    dacConfig->dacPinEn = CMP_REG_GetDacPinEnable(regBase);
    dacConfig->dacRefVolt = CMP_REG_GetDacVoltRef(regBase);
    dacConfig->dacValue = CMP_REG_GetDacVoltValue(regBase);
    dacConfig->dacEn = CMP_REG_GetDacEnable(regBase);
}

/*******************************************************************************
 *** Function Name : CMP_GetDacDefaultConfig
 *** Description   : Get dac default configuration with reset value
 ******************************************************************************/
void CMP_GetDacDefaultConfig(cmp_dac_config_t* dacConfig)
{
    ASSERT_PARAM(dacConfig != NULL);

    /* Get dac default configuration */
    dacConfig->srcClk = CMP_CLK_SRC_OFF;
    dacConfig->dacPinEn = false;
    dacConfig->dacRefVolt = CMP_DAC_BANDGAP;
    dacConfig->dacValue = 0U;
    dacConfig->dacEn = false;
}

/*******************************************************************************
 *** Function Name : CMP_SetDacValue
 *** Description   : Set dac value, 0-255
 ******************************************************************************/
void CMP_SetDacValue(uint32_t instance, uint8_t value)
{
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);
    ASSERT_PARAM(value <= 255U);

    CMP_Type* regBase = s_cmpRegBase[instance];

    CMP_REG_SetDacVoltValue(regBase, value);
}

/*******************************************************************************
 *** Function Name : CMP_SetPosPortInput
 *** Description   : Set comparator positive input channel
 ******************************************************************************/
void CMP_SetPosPortInput(uint32_t instance, cmp_channel_select_t channel)
{
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);
    ASSERT_PARAM(channel <= BG_VOLTAGE);

    CMP_Type* regBase = s_cmpRegBase[instance];

    CMP_REG_SetPosPortInput(regBase, channel);
}

/*******************************************************************************
 *** Function Name : CMP_SetNegPortInput
 *** Description   : Set comparator negative input channel
 ******************************************************************************/
void CMP_SetNegPortInput(uint32_t instance, cmp_channel_select_t channel)
{
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);
    ASSERT_PARAM(channel <= BG_VOLTAGE);

    CMP_Type* regBase = s_cmpRegBase[instance];

    CMP_REG_SetNegPortInput(regBase, channel);
}

/*******************************************************************************
 *** Function Name : CMP_GetNormalModeOutput
 *** Description   : Get comparator normal mode output result
 ******************************************************************************/
uint8_t CMP_GetNormalModeOutput(uint32_t instance)
{
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    uint8_t retValue = 0U;
    CMP_Type* regBase = s_cmpRegBase[instance];

    retValue = CMP_REG_GetNormalModeOutput(regBase);

    return retValue;
}

/*******************************************************************************
 *** Function Name : CMP_GetLoopModeOutput
 *** Description   : Get comparator loop mode output result
 ******************************************************************************/
uint16_t CMP_GetLoopModeOutput(uint32_t instance)
{
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);

    uint16_t retValue = 0U;
    CMP_Type* regBase = s_cmpRegBase[instance];

    retValue = CMP_REG_GetLoopModeOutput(regBase);

    return retValue;
}

/*******************************************************************************
 *** Function Name : CMP_FilterParamConvert
 *** Description   : Comparator digital filter parameters convert, cmpClock / (filterClkDiv + 1) / filterFerq result need to be guaranteed to be an integer
 ******************************************************************************/
void CMP_FilterParamConvert(uint32_t instance, uint32_t filterFerq, cmp_comparator_config_t* compConfig)
{
    ASSERT_PARAM(instance < CONFIG_CMP_INSTANCE_COUNT);
    ASSERT_PARAM(compConfig != NULL);

    uint32_t cmpClock = 0U;
    clk_names_t cmpClkName = s_cmpClkName[instance];
    uint16_t filterClkDiv = 0U;

    (void)CLOCK_GetFreq(cmpClkName, &cmpClock);

    ASSERT_PARAM(cmpClock > 0U);
    ASSERT_PARAM((cmpClock / (filterClkDiv + 1U)) >= filterFerq);
    ASSERT_PARAM((cmpClock / (filterClkDiv + 1U) / filterFerq) < 256U);

    compConfig->digFilterConfig.filterEn = true;
    compConfig->digFilterConfig.filterClockDiv = filterClkDiv;
    compConfig->digFilterConfig.filterWidth = (uint8_t)(cmpClock / (filterClkDiv + 1U) / filterFerq);
}

/*******************************************************************************
 *** Function Name : CMP_IRQHandlerProcess
 *** Description   : CMP interrupt implement
 ******************************************************************************/
void CMP_IRQHandlerProcess(uint32_t instance)
{
    CMP_Type* regBase = s_cmpRegBase[instance];
    cmp_int_status_t* intStatus = &s_cmpIntStatus[instance];

    intStatus->intFlag = CMP_REG_GetIntFlags(regBase);
    if (intStatus->intFlag) {
        CMP_REG_ClrIntFlags(regBase);

        if (NULL != s_cmpCallback[instance]) {
            s_cmpCallback[instance](instance, (void*)intStatus);
        }
    }
}

/*******EOF********************************************************************/
